package com.piggy.common.netty.ws.server;

import com.piggy.netty.ws.annotation.*;
import com.piggy.netty.ws.pojo.Session;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpHeaders;
import org.springframework.util.MultiValueMap;

import java.io.IOException;
import java.util.Map;

@ConditionalOnProperty(name = "spring.netty.ws")
@ServerEndpoint(value = "/ws/{sid}", port = "${spring.netty.ws.port}",
        workerLoopGroupThreads = "${spring.netty.ws.workerThread}",
        bossLoopGroupThreads = "${spring.netty.ws.bossThread}",
        allIdleTimeSeconds = "${spring.netty.ws.idleTime:60}"
)
@Slf4j
public class NettyServer {

    @BeforeHandshake
    public void handshake(Session session, @PathVariable("sid") String sid, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
        session.setSubprotocols("stomp");
        if (!"ok".equals(req)){
            System.out.println("Authentication failed!");
            session.close();
        }
    }

    @OnOpen
    public void onOpen(Session session, @PathVariable("sid") String sid, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
        System.out.println("new connection");
        System.out.println(req);
    }

    @OnClose
    public void onClose(@PathVariable("sid") String sid, Session session) throws IOException {
        System.out.println("one connection closed");
    }

    @OnError
    public void onError(@PathVariable("sid") String sid, Session session, Throwable throwable) {
        throwable.printStackTrace();
    }

    @OnMessage
    public void onMessage(@PathVariable("sid") String sid, Session session, String message) {
        System.out.println(message);
        session.sendText("Hello Netty!");
    }

    @OnBinary
    public void onBinary(@PathVariable("sid") String sid, Session session, byte[] bytes) {
        for (byte b : bytes) {
            System.out.println(b);
        }
        session.sendBinary(bytes);
    }

    @OnEvent
    public void onEvent(@PathVariable("sid") String sid, Session session, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            switch (idleStateEvent.state()) {
                case READER_IDLE:
                    System.out.println("read idle");
                    break;
                case WRITER_IDLE:
                    System.out.println("write idle");
                    break;
                case ALL_IDLE:
                    System.out.println("all idle");
                    break;
                default:
                    break;
            }
        }
    }
}
